#include <task/sched.h>

#include <arch/processor.h>
#include <arch/lapic.h>

#include <mm/heap.h>

#include <drv/serial.h>

#include <utils/list.h>
#include <utils/memutils.h>
#include <utils/lock.h>

typedef struct {
	list_node_t node;

	task_block_t *task_block;
} sched_task_t;

static sched_task_t *sched_tasks = NULL;
static lock_t sched_lock;

intr_regs_frame_t *sched_tick(intr_regs_frame_t *frame) {
	lock_acquire(&sched_lock);

	processor_t *self = processor_get_current();
	task_block_t *prev = self->current_task;
	task_block_t *next = NULL;

	//	找一个可以运行的task
	if(__likely(sched_tasks)) {
		sched_task_t *entry = sched_tasks;
		sched_task_t *last = (sched_task_t *)list_get_last_node(&sched_tasks->node);

		while(entry != last) {
			if(entry->task_block->task_state == TASK_STATE_READY) {
				next = entry->task_block;
				sched_tasks = (sched_task_t *)list_next_node(&entry->node);
				break;
			}

			entry = (sched_task_t *)list_next_node(&entry->node);
		}
	}

	//	找不到可以运行的task就运行idle task
	if(__unlikely(!next)) {
		next = self->idle_task;
	}

	//	保存上个task的上下文并释放它
	if(__likely(prev)) {
		prev->task_stack_top = (uint64_t)frame;
		prev->last_tick = self->sched_tick_counter;

		if(prev->task_state == TASK_STATE_RUNNING) {
			prev->task_state = TASK_STATE_READY;
		}
	}

	//	占有要运行的task
	self->current_task = next;
	next->task_state = TASK_STATE_RUNNING;

	lock_release(&sched_lock);

	self->tss.rsp[0] = next->kstack_top;

	++self->sched_tick_counter;

	return (intr_regs_frame_t *)next->task_stack_top;
}

uint64_t sched_get_tick() {
	return processor_get_current()->sched_tick_counter;
}

void sched_add_task(task_block_t *task) {
	lock_acquire(&sched_lock);

	sched_task_t *entry = mm_heap_zeroalloc(sizeof(sched_task_t));
	entry->task_block = task;

	if(__unlikely(!sched_tasks)) {
		sched_tasks = entry;
		list_make_circular(&sched_tasks->node);
	} else {
		list_append(&sched_tasks->node, &entry->node);
	}

	lock_release(&sched_lock);
}